﻿/**********************************************************
 ●项目：Smartkernel
 ●公司：智能核心信息技术研发中心
 ●作者：曹艳白
 ●邮箱：caoyanbai@gmail.com
 ●创建：2008-08-10
**********************************************************/
using System.CodeDom.Compiler;
using System.Reflection;
using Smartkernel.Caching;
using Microsoft.CSharp;

namespace Smartkernel
{
    /// <summary>
    /// 智能编译类，提供动态编译的相关功能。如动态计算表达式的值等
    /// </summary>
    public static class SmartCodeCompiler
    {
        /// <summary>
        /// 动态编译代码并返回编译之后的程序集合
        /// </summary>
        /// <param name="referencedAssemblies">引用的程序集</param>
        /// <param name="code">要编译的代码文本</param>
        /// <param name="isCache">是否启用高速缓存，如果启用，则相同代码文本只在第一次调用时编译。之后则从高速缓存中获取。高速缓存的数据在应用程序退出时才清空。如果为false，可以由客户端程序员自行控制缓存策略。</param>
        /// <returns>返回编译的程序集</returns>
        public static Assembly Compile(string[] referencedAssemblies, string code, bool isCache)
        {
            Assembly result = null;
            if (isCache)
            {
                string key = code.GetHashCode().ToString();
                string category = "__SmartCodeCompiler__CompileCategory";
                if (SmartMemoryCacher.ContainsKey(category, key))
                {
                    result = (Assembly)SmartMemoryCacher.GetValue(category, key);
                }
                else
                {
                    result = Compile(referencedAssemblies, code);
                    SmartMemoryCacher.Add(category, key, result);
                }
            }
            else
            {
                result = Compile(referencedAssemblies, code);
            }
            return result;
        }
        /// <summary>
        /// 动态编译代码并返回编译之后的程序集合
        /// </summary>
        /// <param name="referencedAssemblies">引用的程序集</param>
        /// <param name="code">要编译的代码文本</param>
        /// <returns>返回编译的程序集</returns>
        private static Assembly Compile(string[] referencedAssemblies, string code)
        {
            CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider();

            //编译的参数
            CompilerParameters compilerParameters = new CompilerParameters();
            compilerParameters.ReferencedAssemblies.AddRange(referencedAssemblies);
            compilerParameters.CompilerOptions = "/t:library";
            compilerParameters.GenerateInMemory = true;
            //开始编译
            CompilerResults compilerResults = csharpCodeProvider.CompileAssemblyFromSource(compilerParameters, code);
            return compilerResults.CompiledAssembly;
        }
    }
}
